package com.frank.activedatabus.Core;

import com.frank.activedatabus.dispatch.DispatchManager;
import com.frank.activedatabus.dispatch.ThreadMode;
import ohos.aafwk.ability.Lifecycle;
import ohos.aafwk.abilityjet.activedata.ActiveData;
import ohos.aafwk.abilityjet.activedata.DataObserver;
import ohos.eventhandler.EventHandler;
import ohos.eventhandler.EventRunner;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.UUID;

/**
 * @author : frank
 * @date : 2021/3/5 15:14
 */
class CustomActiveData<T> extends ActiveData {

    private final HashMap<Integer, Boolean> observers = new HashMap<>();
    private final HashMap<Observer, DataObserver> observerMap = new HashMap<>();
    private final String key;
    private EventHandler mainHandler = new EventHandler(EventRunner.getMainEventRunner());
    private EventHandler backgroundHandler = new EventHandler(EventRunner.create("ActiveDataBus"));

    public CustomActiveData(String key) {
        this.key = key;
    }

    public String getKey() {
        return key;
    }

    public void observe(Observer<T> dataChangeListener, Lifecycle lifecycle, boolean always, boolean isSticky, ThreadMode threadMode) {
        Integer storeId = System.identityHashCode(UUID.randomUUID());
        if (observerMap.containsKey(dataChangeListener)) {
            return;
        }
        if (lifecycle == null) {
            lifecycle = new CustomLifeCycle();
            ((CustomLifeCycle)lifecycle).register();
        }
        if (observers.get(storeId) == null) {
            observers.put(storeId, true);
        }
        DataObserver<T> observer = new DataObserver<T>() {

            @Override
            public void onChanged(T t) {
                if (isSticky) {
                    dispatchEvent(t);
                } else {
                    if (!observers.get(storeId)) {
                        observers.put(storeId, true);
                        if (t != null) {
                            dispatchEvent(t);
                        }
                    }
                }
            }

            private void dispatchEvent(T t) {
                DispatchManager.getInstance().getDispatch(threadMode).post(() -> {
                    dataChangeListener.onDataChange(t);
                });
            }
        };

        observer.setLifecycle(lifecycle);

        observerMap.put(dataChangeListener, observer);

        addObserver(observer, always);
    }

    @Override
    public void removeObserver(DataObserver observer) {
        super.removeObserver(observer);
        Iterator<Map.Entry<Observer,DataObserver>> entries = observerMap.entrySet().iterator();
        while (entries.hasNext()) {
            Map.Entry<Observer, DataObserver> entry = entries.next();
            DataObserver value = entry.getValue();
            if (value == observer){
                observerMap.remove(value);
            }
            return;
        }
    }

    public void removeObserver(Observer dataChangeListener) {
        DataObserver<T> realObserver = null;
        if (observerMap.containsKey(dataChangeListener)) {
            realObserver = observerMap.remove(dataChangeListener);
        }
        if (realObserver != null) {
            super.removeObserver(realObserver);
        }
    }

    @Override
    public void setData(Object value) {
        if (value != null) {
            for (Map.Entry<Integer, Boolean> entry : observers.entrySet()) {
                entry.setValue(false);
            }
            super.setData(value);
        }
    }
}
